﻿using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using EnvDTE;
using EnvDTE80;
using System.Reflection;
using System;
using SolutionNavigateAddIn.Watcher;

namespace SolutionNavigateAddIn
{
    public static class SnEnvironment
    {
        private static Command openComboBoxCommand;
        private static TextWriterTraceListener listener;
        static SnEnvironment()
        {
            Settings = SnSettings.GetSettings();
            FileInfo info = new FileInfo(Path.Combine(ProgramDataDirectory, "solutionNavigater.log"));
            listener = new TextWriterTraceListener(info.FullName);
        }

        public static DTE2 MainDTE { get; set; }

        public static SnSettings Settings { get; set;}

        public static AddIn AddIn { get; set; }

        public static string OpenComboBoxCommandName
        {
            get
            {
                return "SolutionNavigateAddIn.Connect.SolutionNavigatorOpenComboBox";
            }
        }

        private static string programDataDirectory = null;
        public static string ProgramDataDirectory
        {

            get
            {
                if (programDataDirectory == null)
                {
                    string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
                                               "Solution Navigator");
                    DirectoryInfo info = new DirectoryInfo(path);
                    if (!info.Exists)
                        info.Create();

                    programDataDirectory = info.FullName;
                }

                return programDataDirectory;
            }
        }

        public static void Connect()
        {
            if (Settings.CanTrace && listener != null)
                Trace.Listeners.Add(listener);

            RegisterNewCommand();
            SnEvents.Activate();
            SolutionWatcher.Activate();
        }

        private static void RegisterNewCommand()
        {
            try
            {
                object[] contextGUIDS = new object[] { };
                openComboBoxCommand = GetComboBoxCommand(contextGUIDS);

                if (openComboBoxCommand != null)
                    SnEvents.RegisterComboBoxCommand(openComboBoxCommand);

            }
            catch (Exception e)
            {
                Trace.WriteLine(
                     string.Format(
                         "Not enought create openComboBoxCommand, generate exception: {0}",
                         e.Message));
            }
        }

        private static Command GetComboBoxCommand(object[] contextGUIDS)
        {
            Command command = null;
            
            Commands2 commands = (Commands2)MainDTE.Commands;

            foreach (Command item in commands)
            {
                if (item.Name == OpenComboBoxCommandName)
                {
                    command = item;
                    break;
                }
            }

            if (command == null)
            {
                command = commands.AddNamedCommand2(AddIn,
                                                    "SolutionNavigatorOpenComboBox", "OpenComboBox",
                                                    "Open ComboBox in Solution Navigator.", true, null, ref contextGUIDS,
                                                    (int) vsCommandStatus.vsCommandStatusSupported +
                                                    (int) vsCommandStatus.vsCommandStatusEnabled,
                                                    (int) vsCommandStyle.vsCommandStyleText,
                                                    vsCommandControlType.vsCommandControlTypeButton);
            }

            if (!string.IsNullOrEmpty(Settings.GlobalKey))
            {
                try
                {
                    command.Bindings = new object[] { Settings.GlobalKey };
                }
                catch (Exception e)
                {
                    Trace.WriteLine(string.Format("Not valid shortkey. Message: {0}", e.Message));
                    Settings.GlobalKey = string.Empty;
                }
            }

            return command;
        }

        public static void Startup()
        {
            AssemblyFileVersionAttribute[] attributes =
                (AssemblyFileVersionAttribute[])
                Assembly.GetAssembly(typeof (SnEnvironment)).GetCustomAttributes(typeof (AssemblyFileVersionAttribute),
                                                                                 false);
            Version currentVersion = new Version();
            if (attributes.Length > 0)
            {
                try
                {
                    currentVersion = new Version(attributes[0].Version);
                }
                catch
                {

                    currentVersion = new Version();
                }
            }

            if (Settings.ShowSettings ||
                Settings.GetVersion() < currentVersion)
            {
                using (StartupForm form = new StartupForm())
                {
                    form.InitSettings(Settings);
                    form.ShowDialog();

                    bool save = false;
                    if (!Settings.ShowSettings.Equals(form.ShowSettings))
                    {
                        save = true;
                        Settings.ShowSettings = form.ShowSettings;
                    }

                    if (!Settings.CanTrace.Equals(form.CanTrace))
                    {
                        save = true;
                        Settings.CanTrace = form.CanTrace;
                        if (Settings.CanTrace)
                        {
                            if (listener != null && !Trace.Listeners.Contains(listener))
                            {
                                Trace.Listeners.Add(listener);
                            }
                            else
                            {
                                if (listener != null && Trace.Listeners.Contains(listener))
                                {
                                    Trace.Listeners.Remove(listener);
                                }
                            }
                        }
                    }

                    if (!string.Equals(Settings.GlobalKey,form.GlobalKey))
                    {
                        save = true;
                        Settings.GlobalKey = form.GlobalKey;
                        if (openComboBoxCommand != null)
                        {
                            openComboBoxCommand.Bindings = new object[] { Settings.GlobalKey };
                        }
                    }

                    if (!string.Equals(Settings.Version, currentVersion.ToString()))
                    {
                        save = true;
                        Settings.Version = currentVersion.ToString();
                    }

                    if (save)
                        SnSettings.SaveSettings(Settings);
                }
            }
        }

        public static void Shutdown()
        {
            bool save = false;
            if (openComboBoxCommand != null)
            {
                string key = string.Empty;

                object[] objects = openComboBoxCommand.Bindings as object[];
                if (objects != null && objects.Length > 0)
                    key = objects[0].ToString();

                if (!string.Equals(Settings.GlobalKey, key))
                {
                    save = true;
                    Settings.GlobalKey = key;
                }
            }

            if (save)
                SnSettings.SaveSettings(Settings);
        }

        public static List<string> CheckShortcutUsage(string key)
        {
            List<string> elements = new List<string>();
            string searchMatch;
            int keyIndex = key.IndexOf("::");

            if (keyIndex != -1)
                searchMatch = key.Substring(keyIndex + 2, key.Length - (keyIndex + 2));
            else
                searchMatch = key;

            foreach (Command command in MainDTE.Commands)
            {
                object[] bindings = command.Bindings as object[];

                if (bindings == null)
                    continue;

                for (int i = 0; i < bindings.Length; i++)
                {
                    string commandShortcut = bindings[i].ToString();
                    int index  = commandShortcut.IndexOf("::");
                    if (index != -1)
                    {
                        commandShortcut = commandShortcut.Substring(index + 2, commandShortcut.Length - (index+2));
                    }

                    if (commandShortcut == searchMatch)
                    {
                        elements.Add(string.Format("{0} ({1})", command.Name, bindings[i]));
                    }

                }
            }

            return elements;
        }

       
    }
}